#include "amp_sigiface_dev.h"
#include "amp_mailbox.h"

#define DBG_TAG "sigiface_dev"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

#ifdef PKG_INTER_CORE_USING_HW_MAILBOX
static rt_device_t mbox_dev = RT_NULL;
#endif

#define AMP_MBOX_DEV_NAME "amp_mbox"

static int amp_sigiface_init(int sigiface_id,  rt_sem_t sigiface_sem, void (*sigiface_callback)(int vector, void *param))
{
#if defined(PKG_INTER_CORE_USING_IPI)
    rt_hw_interrupt_install(sigiface_id, sigiface_callback, sigiface_sem, "OPENAMP IPI_HANDLER");
    rt_hw_interrupt_umask(sigiface_id);
#elif defined(PKG_INTER_CORE_USING_HW_MAILBOX)
    struct mbox_configure cfg = {0};

    mbox_dev = rt_device_find(AMP_MBOX_DEV_NAME);
    if(mbox_dev == RT_NULL)
    {
        LOG_E("%s device not found", AMP_MBOX_DEV_NAME);
        return -1;
    }

    cfg.channel = sigiface_id;
    cfg.mbox_callback = sigiface_callback;
    cfg.param = sigiface_sem;
    cfg.init_msg.cmd = MBOX_RPMSG_MAGIC0;
    cfg.init_msg.data = MBOX_RPMSG_MAGIC1;

    rt_device_open(mbox_dev, RT_DEVICE_OFLAG_RDWR);
    rt_device_control(mbox_dev, RT_DEVICE_CTRL_CONFIG, (void *)&cfg);
#endif

    return 0;
}

static int amp_sigiface_send(int sigiface_id, rt_uint8_t remote_cpu)
{
#if defined(PKG_INTER_CORE_USING_IPI)
    static rt_uint32_t          cpu_mask;

    /* call SGI to generate notify */
    LOG_D("send to CPU#%d openamp_notify ...SGI(%d)", remote_cpu, sigiface_id);

    cpu_mask = 1 << remote_cpu;
    rt_hw_ipi_send(sigiface_id, cpu_mask);
#elif defined(PKG_INTER_CORE_USING_HW_MAILBOX)
    struct mbox_cmd_data msg = {0};

    msg.cmd = MBOX_RPMSG_MAGIC0;
    msg.data = MBOX_RPMSG_MAGIC1 | (remote_cpu & 0xF);
    rt_device_write(mbox_dev, sigiface_id, &msg, sizeof(struct mbox_cmd_data));
#endif /* PKG_INTER_CORE_USING_IPI */
    return 0;
}

static struct amp_sigiface_ops amp_sigiface_ops =
{
    .sigiface_init = amp_sigiface_init,
    .sigiface_send = amp_sigiface_send,
};

int amp_sigiface_dev_create(struct amp_sigiface_ops **sigiface_ops)
{
    *sigiface_ops = &amp_sigiface_ops;

    return 0;
}

